#include "ej_bsp_iic.h"
#include <string.h>
#include <stdlib.h>

/*---------------------------- Internal Configuration --------------------------*/
#define MAX_BUSES       4   // 最大支持总线数量
#define MAX_DEVICES     8   // 最大支持设备数量
#define I2C_RETRY_DELAY 10  // 超时重试延迟（us）

#define __I2C_GPIO_USER_DEALY(bus)   bus->drv_info.cfg.sw.delay_us(bus->drv_info.cfg.sw.clock_delay)

#define __I2C_GPIO_SCL_HIGH(bus)     bus->drv_info.cfg.sw.scl_set(TRUE)
#define __I2C_GPIO_SCL_LOW(bus)      bus->drv_info.cfg.sw.scl_set(FALSE)

#define __I2C_GPIO_SDA_HIGH(bus)     bus->drv_info.cfg.sw.sda_set(TRUE)
#define __I2C_GPIO_SDA_LOW(bus)      bus->drv_info.cfg.sw.sda_set(FALSE)

#define __I2C_GPIO_SDA_INPUT(bus)    bus->drv_info.cfg.sw.sda_dir(TRUE)
#define __I2C_GPIO_SDA_OUTPUT(bus)   bus->drv_info.cfg.sw.sda_dir(FALSE)

#define __I2C_GPIO_SDA_VAL_GET(bus)  bus->drv_info.cfg.sw.sda_read()

/*---------------------------- Internal Data Structures ------------------------*/
static struct {
    i2c_bus_t buses[MAX_BUSES];     // 总线实例池
    i2c_device_t devices[MAX_DEVICES]; // 设备实例池
    uint8_t bus_count;              // 已注册总线数量
    uint8_t device_count;           // 已挂载设备数量
} i2c_manager = {0};

/*---------------------------- Internal Helper Functions -----------------------*/

// 根据名称查找总线
static i2c_bus_t* find_bus(const char *bus_name) {
    for (uint8_t i = 0; i < i2c_manager.bus_count; i++) {
        if (strcmp(i2c_manager.buses[i].bus_name, bus_name) == 0) {
            return &i2c_manager.buses[i];
        }
    }
    return NULL;
}

// 根据名称查找设备
static i2c_device_t* find_device(const char *dev_name) {
    for (uint8_t i = 0; i < i2c_manager.device_count; i++) {
        if (strcmp(i2c_manager.devices[i].dev_name, dev_name) == 0) {
            return &i2c_manager.devices[i];
        }
    }
    return NULL;
}

// 获取系统时间戳（需用户实现）
static uint32_t get_timestamp_ms(void) {
    // 示例：假设用户提供了此函数
    extern uint32_t com_get_sys_tick(void);
    return com_get_sys_tick();
}

// 检查超时（单位ms）
static i2c_status_t check_timeout(uint32_t start_time, uint32_t timeout_ms) {
    if (timeout_ms == 0) return I2C_OK;
    if ((get_timestamp_ms() - start_time) >= timeout_ms) {
        return I2C_ERR_TIMEOUT;
    }
    return I2C_OK;
}

/*---------------------------- Modified Software I2C Implementation -----------------------*/
// 新增时序控制宏（确保高低电平时间对称）
#define __I2C_HALF_CYCLE_DELAY(bus)  do { \
    bus->drv_info.cfg.sw.delay_us(bus->drv_info.cfg.sw.clock_delay / 2); \
} while(0)

#define __I2C_FULL_CYCLE_DELAY(bus)  do { \
    bus->drv_info.cfg.sw.delay_us(bus->drv_info.cfg.sw.clock_delay); \
} while(0)

// 优化后的起始信号（增加严格的时序控制）
static void sw_i2c_start(i2c_bus_t *bus) {
    __I2C_GPIO_SDA_HIGH(bus);
    __I2C_GPIO_SCL_HIGH(bus);
    __I2C_FULL_CYCLE_DELAY(bus);
    
    __I2C_GPIO_SDA_LOW(bus);
    __I2C_HALF_CYCLE_DELAY(bus);
    
    __I2C_GPIO_SCL_LOW(bus);
    __I2C_FULL_CYCLE_DELAY(bus);
}

static void sw_i2c_restart(i2c_bus_t *bus)
{
    __I2C_GPIO_SDA_HIGH(bus);
    __I2C_GPIO_SCL_HIGH(bus);
    __I2C_FULL_CYCLE_DELAY(bus);

    __I2C_GPIO_SDA_LOW(bus);
    __I2C_HALF_CYCLE_DELAY(bus);

	__I2C_GPIO_SCL_LOW(bus);					
}	

// 优化后的停止信号（确保满足建立时间要求）
static void sw_i2c_stop(i2c_bus_t *bus) {
    __I2C_GPIO_SDA_LOW(bus);
    __I2C_HALF_CYCLE_DELAY(bus);
    
    __I2C_GPIO_SCL_HIGH(bus);
    __I2C_FULL_CYCLE_DELAY(bus);
    
    __I2C_GPIO_SDA_HIGH(bus);
    __I2C_FULL_CYCLE_DELAY(bus);
}

// 优化后的ACK检测（增加超时保护）
static bool sw_i2c_ack_get(i2c_bus_t *bus) {
    bool acked = FALSE;
    
    __I2C_GPIO_SDA_HIGH(bus);
    __I2C_GPIO_SDA_INPUT(bus);
    __I2C_HALF_CYCLE_DELAY(bus);
    
    __I2C_GPIO_SCL_HIGH(bus);
    __I2C_FULL_CYCLE_DELAY(bus);  // 保证足够采样时间
    
    acked = !__I2C_GPIO_SDA_VAL_GET(bus);
    
    __I2C_GPIO_SCL_LOW(bus);
    __I2C_FULL_CYCLE_DELAY(bus);
    
    __I2C_GPIO_SDA_OUTPUT(bus);
    return acked;
}

// 优化后的ACK/NACK发送（增强时序控制）
static void sw_i2c_ack_put(i2c_bus_t *bus, bool ack) 
{
    __I2C_GPIO_SDA_OUTPUT(bus);
    
    // 设置ACK电平（提前设置确保建立时间）
    ack ? __I2C_GPIO_SDA_LOW(bus) : __I2C_GPIO_SDA_HIGH(bus);
    __I2C_HALF_CYCLE_DELAY(bus);  // 数据建立时间
    
    // 生成时钟脉冲
    __I2C_GPIO_SCL_HIGH(bus);
    __I2C_FULL_CYCLE_DELAY(bus);  // 保证有效采样窗口
    
    __I2C_GPIO_SCL_LOW(bus);
    __I2C_FULL_CYCLE_DELAY(bus);  // 保持时间
    
    // 释放SDA线（为后续操作准备）
    if (!ack) {
        __I2C_GPIO_SDA_HIGH(bus);
    }
}

// 优化后的数据发送（确保数据建立/保持时间）
static bool sw_i2c_send_byte(i2c_bus_t *bus, uint8_t data) {
    for (int i = 7; i >= 0; i--) {
        // 在SCL低电平时改变数据
        (data & (1 << i)) ? __I2C_GPIO_SDA_HIGH(bus) : __I2C_GPIO_SDA_LOW(bus);
        __I2C_HALF_CYCLE_DELAY(bus);
        
        // 上升沿
        __I2C_GPIO_SCL_HIGH(bus);
        __I2C_FULL_CYCLE_DELAY(bus);
        
        // 下降沿
        __I2C_GPIO_SCL_LOW(bus);
        __I2C_FULL_CYCLE_DELAY(bus);
    }
    return sw_i2c_ack_get(bus);
}

// 优化后的数据接收（增加采样稳定性）
static uint8_t sw_i2c_recv_byte(i2c_bus_t *bus, bool ack) {
    uint8_t data = 0;
    
    __I2C_GPIO_SDA_INPUT(bus);
    __I2C_HALF_CYCLE_DELAY(bus);
    
    for (int i = 7; i >= 0; i--) {
        __I2C_GPIO_SCL_HIGH(bus);
        __I2C_FULL_CYCLE_DELAY(bus);  // 保证足够采样时间
        
        if (__I2C_GPIO_SDA_VAL_GET(bus)) {
            data |= (1 << i);
        }
        
        __I2C_GPIO_SCL_LOW(bus);
        __I2C_FULL_CYCLE_DELAY(bus);
    }
    
    sw_i2c_ack_put(bus, ack);
    return data;
}

/*---------------------------- Public API Implementation -----------------------*/

i2c_status_t ej_bsp_i2c_register_bus(const char *bus_name, const i2c_drv_info_t *drv_info) {
    if (i2c_manager.bus_count >= MAX_BUSES) return I2C_ERR_INVALID_CFG;
    if (find_bus(bus_name) != NULL) return I2C_ERR_DEVICE_EXISTS; // 名称冲突

    // 保存总线配置
    i2c_bus_t *bus = &i2c_manager.buses[i2c_manager.bus_count];
    bus->bus_name = bus_name;
    bus->drv_info = *drv_info;
    bus->initialized = false;
    i2c_manager.bus_count++;
    return I2C_OK;
}

i2c_status_t ej_bsp_i2c_init_bus(const char *bus_name)
{
    i2c_bus_t *bus = find_bus(bus_name);
    if (!bus) return I2C_ERR_BUS_NOT_FOUND;

    // 硬件模式初始化
    if (bus->drv_info.mode == I2C_MODE_HW) {
        if (bus->drv_info.cfg.hw.ops.init) {
            bus->drv_info.cfg.hw.ops.init(bus->drv_info.cfg.hw.hw_instance);
        }
    }
    // 软件模式无需额外初始化，但需检查配置有效性
    else if (bus->drv_info.mode == I2C_MODE_SW) {
        sw_i2c_cfg_t *sw_cfg = &bus->drv_info.cfg.sw;
        if (!sw_cfg->scl_set || !sw_cfg->sda_set ||
            !sw_cfg->sda_dir || !sw_cfg->sda_read ||
            !sw_cfg->delay_us) {
            return I2C_ERR_INVALID_CFG;
        }
		if (sw_cfg->gpio_init)
		{
			sw_cfg->gpio_init();
		}
    }
    bus->initialized = true;
    return I2C_OK;
}

i2c_status_t ej_bsp_i2c_attach_device(const char *bus_name, const char *dev_name, uint8_t address) {
    if (i2c_manager.device_count >= MAX_DEVICES) return I2C_ERR_INVALID_CFG;
    if (find_device(dev_name)) return I2C_ERR_DEVICE_EXISTS;
    if (!find_bus(bus_name)) return I2C_ERR_BUS_NOT_FOUND;

    // 保存设备信息
    i2c_device_t *dev = &i2c_manager.devices[i2c_manager.device_count];
    dev->dev_name = dev_name;
    dev->bus_name = bus_name;
    dev->address = address;
    i2c_manager.device_count++;
    return I2C_OK;
}

i2c_status_t ej_bsp_i2c_write_to_device(const char *dev_name, const uint8_t *data, uint16_t len, uint32_t timeout_ms) 
{
    i2c_device_t *dev = find_device(dev_name);
    if (!dev) return I2C_ERR_DEVICE_NOT_FOUND;
    i2c_bus_t *bus = find_bus(dev->bus_name);
    if (!bus || !bus->initialized) return I2C_ERR_BUS_NOT_INIT;

    if (bus->drv_info.mode == I2C_MODE_HW) 
	{
        return bus->drv_info.cfg.hw.ops.write(
            bus->drv_info.cfg.hw.hw_instance,
            dev->address,
            data,
            len,
            timeout_ms
        );
    }
    else // 软件模式
	{ 
        sw_i2c_start(bus);
        // 发送设备地址（写模式）
		if (sw_i2c_send_byte(bus, (dev->address << 1) | 0x00) == FALSE)
		 {
			 sw_i2c_stop(bus);
			 return I2C_ERR_NACK;
		 }


        // 发送数据
        for (uint16_t i = 0; i < len; i++)
		{       
			if (sw_i2c_send_byte(bus, data[i]) == FALSE)
			{
				 sw_i2c_stop(bus);
				 return I2C_ERR_NACK;
			}
        }
        sw_i2c_stop(bus);
        return I2C_OK;
    }
}

i2c_status_t ej_bsp_i2c_read_from_device(const char *dev_name, uint8_t *buf, uint16_t len, uint32_t timeout_ms)
{
    i2c_device_t *dev = find_device(dev_name);
    if (!dev) return I2C_ERR_DEVICE_NOT_FOUND;
    i2c_bus_t *bus = find_bus(dev->bus_name);
    if (!bus || !bus->initialized) return I2C_ERR_BUS_NOT_INIT;

    if (bus->drv_info.mode == I2C_MODE_HW) 
	{
        return bus->drv_info.cfg.hw.ops.read(
            bus->drv_info.cfg.hw.hw_instance,
            dev->address,
            buf,
            len,
            timeout_ms
        );
    }
    else  // 软件模式
	{
       	sw_i2c_start(bus);
        // 发送设备地址（读模式）
		if (sw_i2c_send_byte(bus, (dev->address << 1) | 0x01) == FALSE)
		{
			 sw_i2c_stop(bus);
			 return I2C_ERR_NACK;
		}

        // 接收数据
        for (uint16_t i = 0; i < len; i++)
		{
            uint8_t ack = (i == len - 1) ? 0 : 1;
            buf[i] = sw_i2c_recv_byte(bus, ack);
        }
        sw_i2c_stop(bus);
        return I2C_OK;
    }
}

i2c_status_t ej_bsp_i2c_write_read(const char *dev_name, const uint8_t *cmd, uint16_t cmd_len, 
												uint8_t *resp, uint16_t resp_len, 
												uint32_t timeout_ms)
{
    i2c_device_t *dev = find_device(dev_name);
    if (!dev) return I2C_ERR_DEVICE_NOT_FOUND;
    i2c_bus_t *bus = find_bus(dev->bus_name);
    if (!bus || !bus->initialized) return I2C_ERR_BUS_NOT_INIT;

    if (cmd == NULL || cmd_len == 0 || resp == NULL || resp_len == 0) {
        return I2C_ERR_NOT_PARAM;
    }

    if (bus->drv_info.mode == I2C_MODE_SW) {
        // 软件模式实现连续读写
        sw_i2c_start(bus);
        
        // 发送设备地址（写模式）
        if (!sw_i2c_send_byte(bus, (dev->address << 1) | 0x00)) {
            sw_i2c_stop(bus);
            return I2C_ERR_NACK;
        }
        
        // 发送命令数据
        for (uint16_t i = 0; i < cmd_len; i++) {
            if (!sw_i2c_send_byte(bus, cmd[i])) {
                sw_i2c_stop(bus);
                return I2C_ERR_NACK;
            }
        }
        
        // 发送重复起始条件
        sw_i2c_restart(bus);
        
        // 发送设备地址（读模式）
        if (!sw_i2c_send_byte(bus, (dev->address << 1) | 0x01)) {
            sw_i2c_stop(bus);
            return I2C_ERR_NACK;
        }
        
        // 读取响应数据
        for (uint16_t i = 0; i < resp_len; i++) {
            bool ack = (i == resp_len - 1) ? FALSE : TRUE;
            resp[i] = sw_i2c_recv_byte(bus, ack);
        }
        sw_i2c_stop(bus);
        return I2C_OK;
    } else if (bus->drv_info.mode == I2C_MODE_HW) {
        if (bus->drv_info.cfg.hw.ops.write_read) {
            return bus->drv_info.cfg.hw.ops.write_read(
                bus->drv_info.cfg.hw.hw_instance,
                dev->address,
                cmd, cmd_len,
                resp, resp_len,
                timeout_ms
            );
        }
        // 若驱动未实现，返回错误
        return I2C_ERR_INVALID_CFG;
    }
    return I2C_ERR_INVALID_CFG;
}

/* --------------------------Expand API-----------------------------*/
i2c_status_t ej_bsp_i2c_reg_write_byte(const char *dev_name, uint8_t reg, uint8_t value, uint32_t timeout_ms)
{
    uint8_t buffer[2] = {reg, value};
    return ej_bsp_i2c_write_to_device(dev_name, buffer, sizeof(buffer), timeout_ms);
}

i2c_status_t ej_bsp_i2c_reg_read_byte(const char *dev_name, uint8_t reg, uint8_t *value, uint32_t timeout_ms)
{
    i2c_status_t status = ej_bsp_i2c_write_to_device(dev_name, &reg, 1, timeout_ms);
    if (status != I2C_OK) return status;
    return ej_bsp_i2c_read_from_device(dev_name, value, 1, timeout_ms);
}

i2c_status_t ej_bsp_i2c_reg_write_burst(const char *dev_name, uint8_t reg, const uint8_t *data, uint16_t len, uint32_t timeout_ms)
{
    uint8_t *buffer = (uint8_t*)malloc(len + 1);
    if (!buffer) return I2C_ERR_INVALID_CFG;
    buffer[0] = reg;
    memcpy(buffer + 1, data, len);
    i2c_status_t status = ej_bsp_i2c_write_to_device(dev_name, buffer, len + 1, timeout_ms);
    free(buffer);
    return status;
}

i2c_status_t ej_bsp_i2c_reg_read_burst(const char *dev_name, uint8_t reg, uint8_t *data, uint16_t len, uint32_t timeout_ms)
{
    i2c_status_t status = ej_bsp_i2c_write_to_device(dev_name, &reg, 1, timeout_ms);
    if (status != I2C_OK) return status;
    return ej_bsp_i2c_read_from_device(dev_name, data, len, timeout_ms);
}

i2c_status_t ej_bsp_i2c_probe_device(const char *dev_name, uint32_t timeout_ms)
{
    return ej_bsp_i2c_write_to_device(dev_name, NULL, 0, timeout_ms);
}


